package com.fita.wechat.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fita.wechat.helper.impl.VehiclePriceHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.utils.JsonUtils;
import com.fita.entity.data.Country;
import com.fita.entity.data.Location;
import com.fita.entity.data.Supplier;
import com.fita.entity.data.VehicleParameter;
import com.fita.entity.dto.ehi.response.VehicleCore;
import com.fita.entity.dto.ehi.response.VehicleCoreCharge;
import com.fita.entity.dto.ehi.response.VehicleCoreFee;
import com.fita.entity.order.PayType;
import com.fita.entity.set.Set;
import com.fita.entity.set.SetCategory;
import com.fita.entity.set.SetPayType;
import com.fita.entity.set.SetStatus;
import com.fita.wechat.dao.CarDao;
import com.fita.wechat.entity.CarDetail;
import com.fita.wechat.entity.CarsSearch;
import com.fita.wechat.entity.Shopping;
import com.fita.wechat.handler.EhiHandler;
import com.fita.wechat.service.CarService;

/**
 * 
 * @author mohanlan
 *
 */
@Service("carService")
public class CarServiceImpl implements CarService {
    
    private static final Logger logger = LoggerFactory.getLogger(CarServiceImpl.class);
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Autowired
    private EhiHandler ehiHandler;
    
    @Dao
    private CarDao carDao;

    /*
     * (non-Javadoc)
     * @see com.fita.wechat.service.CarService#generateSearchParams(com.fita.wechat.entity.CarsSearch)
     */
    private Map<String, Object> generateSearchVehicleParams(CarsSearch carsSearch) {
        
        Supplier supplier = genericDaoSupport.load(Supplier.class, carsSearch.getSupplierId());
        
        Location pickupLocation = genericDaoSupport.load(Location.class, carsSearch.getPickupLocation());
        Location returnLocation = genericDaoSupport.load(Location.class, carsSearch.getReturnLocation());
        
        if((supplier == null || supplier.getId() == null) || 
           (pickupLocation == null || pickupLocation.getId() == null) || 
           (returnLocation == null || returnLocation.getId() == null)) {
            logger.error("generateSearchParams occurs error : 查询参数异常, [{}]", JsonUtils.toJson(carsSearch));
            throw BusinessException.newInstance("500", "查询参数异常");
        }
        
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("brand", supplier.getIata());
        params.put("status", "Available");
        
        // 取车和还车时间设成格林尼治时间
//        Date pickupDate = DateUtils.addHours(carsSearch.getPickupDate(), -8);
//        Date returnDate = DateUtils.addHours(carsSearch.getReturnDate(), -8);

        params.put("pickup_date_time", carsSearch.getPickupDate());
        params.put("return_date_time", carsSearch.getReturnDate());
        params.put("pickup_location", pickupLocation.getCode());
        params.put("return_location", returnLocation.getCode());
        params.put("vendor_pref_code", supplier.getPrefCode());
        params.put("driver_type_age", carsSearch.getDriveAge());
        params.put("rate_qualifier", "CORP");
        
        logger.info("generateSearchParams success with result [{}]", JsonUtils.toJson(params));
        
        return params;
    }
    
    /*
     * (non-Javadoc)
     * @see com.fita.wechat.service.CarService#searchVehicles(com.fita.wechat.entity.CarsSearch, java.util.List)
     */
    public List<VehicleCore> searchVehicles(CarsSearch carsSearch) {
        
        List<Set> sets = this.listSearchSet(carsSearch);
        
        if(sets.isEmpty()) {
            logger.error("searchVehicles - 请求参数错误");
            throw BusinessException.newInstance("400", "请求参数错误");
        }
        
        Map<String, Object> params = this.generateSearchVehicleParams(carsSearch);
        
        if(sets.size() == 1) {
            params.put("set_code", sets.get(0).getCode());
            logger.info("current set id [{}]", sets.get(0).getId());
            List<VehicleCore> vehicleCores = ehiHandler.searchAvaliableCars(params);
            
            if(vehicleCores == null || vehicleCores.isEmpty()) {
                throw BusinessException.newInstance("400", "请求参数错误");
            }
            
            for(VehicleCore vehicleCore : vehicleCores) {
                vehicleCore.editPrice(sets.get(0).getId(), sets.get(0).getPayType(), null, null, vehicleCore.getTotalAmount(), null, vehicleCore.getEsimatedTotalAmount(), null);
            }
            
            vehicleCores = this.updateVehicleParam(vehicleCores);
            logger.info("get vehicleCores[{}]", JsonUtils.toJson(vehicleCores));
            return vehicleCores;
        } else if(sets.size() == 2) {
            
            Set set1 = sets.get(0);
            logger.info("current set1 id [{}]", set1.getId());
            params.put("set_code", sets.get(0).getCode());
            List<VehicleCore> vehicleCores = null;
            try {
                vehicleCores = ehiHandler.searchAvaliableCars(params);
                logger.info("get vehicleCores1[{}]", JsonUtils.toJson(vehicleCores));
            } catch (Exception e) {
                logger.error("vehicleCores1 error, exception is [{}]", e);
            }
//            if(vehicleCores == null || vehicleCores.isEmpty()) {
//                return null;
//            }
            
            Set set2 = sets.get(1);
            params.put("set_code", set2.getCode());
            logger.info("current set2 id [{}]", set2.getId());
            List<VehicleCore> vehicleCores2 = null;
            try {
                vehicleCores2 = ehiHandler.searchAvaliableCars(params);
                logger.info("get vehicleCores2[{}]", JsonUtils.toJson(vehicleCores2));
            } catch (Exception e) {
                logger.error("vehicleCores2 error, exception is [{}]", e);
            }
            
            if((vehicleCores == null || vehicleCores.isEmpty()) && (vehicleCores2 != null && !vehicleCores2.isEmpty())) {
                
                for(VehicleCore vehicleCore : vehicleCores2) {
                    vehicleCore.editPrice(sets.get(1).getId(), sets.get(1).getPayType(), null, null, vehicleCore.getTotalAmount(), null, vehicleCore.getEsimatedTotalAmount(), null);
                }
                return this.updateVehicleParam(vehicleCores2);
                
            } else if((vehicleCores2 == null || vehicleCores2.isEmpty()) && (vehicleCores != null && !vehicleCores.isEmpty())) {
                
                for(VehicleCore vehicleCore : vehicleCores) {
                    vehicleCore.editPrice(sets.get(0).getId(), sets.get(0).getPayType(), null, null, vehicleCore.getTotalAmount(), null, vehicleCore.getEsimatedTotalAmount(), null);
                }
                return this.updateVehicleParam(vehicleCores);
                
            } else if((vehicleCores2 != null && !vehicleCores2.isEmpty()) && (vehicleCores != null && !vehicleCores.isEmpty())) {
                Map<String, VehicleCore> vehicleCoresMap2 = new HashMap<>();

                for (VehicleCore vehicleCore2 : vehicleCores2){
                    vehicleCoresMap2.put(vehicleCore2.getModelCode() + vehicleCore2.getModelName(), vehicleCore2);
                }

                for(VehicleCore vehicleCore : vehicleCores) {
//                    for(VehicleCore vehicleCore2 : vehicleCores2) {
//                        if(vehicleCore.getModelName().equalsIgnoreCase(vehicleCore2.getModelName())) {
                    if (vehicleCoresMap2.get(vehicleCore.getModelCode() + vehicleCore.getModelName()) == null) {
                        continue;
                    }
                    if(set1.getPayType().equals(SetPayType.COMMON_PERPAY)) {
                        vehicleCore.editPrice(set1.getId(), set1.getPayType(), set2.getId(), set2.getPayType(), vehicleCore.getTotalAmount(), vehicleCoresMap2.get(vehicleCore.getModelCode() + vehicleCore.getModelName()).getTotalAmount(), vehicleCore.getEsimatedTotalAmount(), vehicleCoresMap2.get(vehicleCore.getModelCode() + vehicleCore.getModelName()).getEsimatedTotalAmount());
                    } else {
                        vehicleCore.editPrice(set2.getId(), set2.getPayType(), set1.getId(), set1.getPayType(), vehicleCoresMap2.get(vehicleCore.getModelCode() + vehicleCore.getModelName()).getTotalAmount(), vehicleCore.getTotalAmount(), vehicleCoresMap2.get(vehicleCore.getModelCode() + vehicleCore.getModelName()).getEsimatedTotalAmount(), vehicleCore.getEsimatedTotalAmount());
                    }
//                        }
//                    }
                }
                
                
              Stream<VehicleCore> stream = vehicleCores.stream().filter(new
              Predicate<VehicleCore>() {
              
              @Override public boolean test(VehicleCore t) { return t.getSet1Id() != null
              && t.getSet2Id() != null; } });
              
              vehicleCores = stream.collect(Collectors.toList());
             
            
                logger.info("get vehicleCores[{}]", JsonUtils.toJson(vehicleCores));
                
                return this.updateVehicleParam(vehicleCores);
            } else if (org.apache.commons.collections.CollectionUtils.isEmpty(vehicleCores) && org.apache.commons.collections.CollectionUtils.isEmpty(vehicleCores2)) {
                throw BusinessException.newInstance("999", "NO VALID PRODUCTS");
            } else {
                throw BusinessException.newInstance("400", "请求参数错误");
            }
            
        } else {
            throw BusinessException.newInstance("500", "套餐数据异常");
        }
    }
    
    /**
     * 
     * @param vehicleCores
     * @return
     */
    private List<VehicleCore> updateVehicleParam(List<VehicleCore> vehicleCores) {
        for(VehicleCore vehicleCore : vehicleCores) {
            if(vehicleCore.getFees() != null && !vehicleCore.getFees().isEmpty()) {
                for(VehicleCoreFee fee : vehicleCore.getFees()) {
                    VehicleParameter parameter = carDao.loadParameter(fee.getDescription());
                    if(parameter == null) {
                        VehicleParameter newParameter = new VehicleParameter(fee.getDescription());
                        genericDaoSupport.save(newParameter);
                        fee.editOrderFeeId(newParameter.getId());
                    } else if(parameter != null && StringUtils.isNotBlank(parameter.getChineseName())) {
                        fee.edit(parameter.getChineseName(), parameter.getId());
                    } else {
                        fee.edit(parameter.getEnglishName(), parameter.getId());
                    }
                }
            }
            
            if (vehicleCore.getVehicleCharges() != null && !vehicleCore.getVehicleCharges().isEmpty()) {
				for (VehicleCoreCharge vehicleCoreCharge : vehicleCore.getVehicleCharges()) {
					VehicleParameter vehicleParameter = carDao.loadParameter(vehicleCoreCharge.getDescription());
					if(vehicleParameter == null) {
                        VehicleParameter newParameter = new VehicleParameter(vehicleCoreCharge.getDescription());
                        genericDaoSupport.save(newParameter);
                        vehicleCoreCharge.editVehicleChargeId(newParameter.getId());
                    } else if(vehicleParameter != null && StringUtils.isNotBlank(vehicleParameter.getChineseName())) {
                    	vehicleCoreCharge.edit(vehicleParameter.getChineseName(), vehicleParameter.getId());
                    } else {
                    	vehicleCoreCharge.edit(vehicleParameter.getEnglishName(), vehicleParameter.getId());
                    }
				}
			}
            
        }
        logger.info("current vehicleCores[{}]", JsonUtils.toJson(vehicleCores));
        return vehicleCores;
    }
    
    /*
     * (non-Javadoc)
     * @see com.fita.wechat.service.CarService#listSearchSet(com.fita.wechat.entity.CarsSearch)
     */
    @SuppressWarnings("unchecked")
    private List<Set> listSearchSet(CarsSearch carsSearch) {
        
        SetCategory setCategory = genericDaoSupport.load(SetCategory.class, carsSearch.getSetCategoryId());
        
        Location pickupLocation = genericDaoSupport.load(Location.class, carsSearch.getPickupLocation());
        String countryCode = pickupLocation.getCountry();
        Country country = genericDaoSupport.searchForObject("FROM Country WHERE disabled = false AND code = :code", "code", countryCode, Country.class);
        
        Supplier supplier = genericDaoSupport.load(Supplier.class, carsSearch.getSupplierId());
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", SetStatus.OPEN);
        params.put("country", country);
        params.put("supplier", supplier);
        params.put("categoty", setCategory);
        
        
        String sentence = "FROM Set WHERE disabled = false AND payType in (:payType) AND categoty = :categoty AND status = :status AND country = :country AND supplier = :supplier";
        if(carsSearch.getType().equals(PayType.ARRIVEPAY)) {
            params.put("payType", new SetPayType[]{SetPayType.ARRIVEPAY});
        } else {
            params.put("payType", new SetPayType[]{SetPayType.COMMON_PERPAY, SetPayType.FLOAT_PREPAY, SetPayType.DYNAMIC_PREPAY});
        }
        
        List<Set> sets = genericDaoSupport.searchForList(sentence, params);
        
        return sets;
    }

    /*
     * (non-Javadoc)
     * @see com.fita.wechat.service.CarService#generateDetailParams(com.fita.entity.dto.ehi.response.VehicleCore)
     */
    public Map<String, Object> generateLocationDetailParams(CarDetail carDetail) {
        
        Country country = genericDaoSupport.load(Country.class, carDetail.getCountryId());
        Supplier supplier = genericDaoSupport.load(Supplier.class, carDetail.getSupplierId());
        
        Location pickupLocation = genericDaoSupport.load(Location.class, carDetail.getPickupLocation());
        
        if((country == null || country.getId() == null) || 
          (supplier == null || supplier.getId() == null)) {
             logger.error("generateDetailParams occurs error : 查询参数异常, [{}]", JsonUtils.toJson(carDetail));
                throw BusinessException.newInstance("500", "查询参数异常");
        }
        
        Set set = genericDaoSupport.load(Set.class, carDetail.getSetId());
        
        // 取车时间和还车时间设成格林尼治时间
//        Date pickupDate = DateUtils.addHours(carDetail.getPickupDate(), -8);
//        Date returnDate = DateUtils.addHours(carDetail.getReturnDate(), -8);
        
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("op_schedule_indicator", true);
        params.put("location_code", pickupLocation.getCode());
        params.put("status", "Available");
        params.put("brand", supplier.getCode());
        params.put("pickup_date_time", carDetail.getPickupDate());
        params.put("return_date_time", carDetail.getReturnDate());
        params.put("set_code", set.getCode());
        params.put("vendor_code", supplier.getPrefCode());
    
        return params;
    }
    
    /*
     * (non-Javadoc)
     * @see com.fita.wechat.service.CarService#generateDetailParams(com.fita.wechat.entity.Shopping)
     */
    public Map<String, Object> generateLocationDetailParams(Shopping shopping) {
        Country country = genericDaoSupport.load(Country.class, shopping.getCountryId());
        Supplier supplier = genericDaoSupport.load(Supplier.class, shopping.getSupplierId());
        Location pickupLocation = genericDaoSupport.load(Location.class, shopping.getPickupLocation());
        
        if((country == null || country.getId() == null) || 
          (supplier == null || supplier.getId() == null)) {
             logger.error("generateDetailParams occurs error : 查询参数异常, [{}]", JsonUtils.toJson(shopping));
                throw BusinessException.newInstance("500", "查询参数异常");
        }
        
        Set set = genericDaoSupport.load(Set.class, shopping.getSetId());
        
        // 取车和还车时间设成格林尼治时间
//        Date pickupDate = DateUtils.addHours(shopping.getPickupDate(), -8);
//        Date returnDate = DateUtils.addHours(shopping.getReturnDate(), -8);
        
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("op_schedule_indicator", true);
        params.put("location_code", pickupLocation.getCode());
        params.put("status", "Available");
        params.put("brand", supplier.getCode());
        params.put("pickup_date_time", shopping.getPickupDate());
        params.put("return_date_time", shopping.getReturnDate());
        params.put("set_code", set.getCode());
        params.put("vendor_code", supplier.getPrefCode());
    
        return params;
    }
}
